package net.stogi.unicore.beyond.ui.client.taskeditor.iotoolbox;

import java.util.List;

import net.stogi.common.gwt.dispatch.client.core.ActionManager;
import net.stogi.common.gwt.frame.client.core.EventBus;
import net.stogi.common.gwt.frame.client.mvp.AbstractPresenter;
import net.stogi.common.mvp.core.behavior.Behavior;
import net.stogi.unicore.beyond.api.model.InputType;
import net.stogi.unicore.beyond.api.model.OutputType;
import net.stogi.unicore.beyond.ui.client.taskeditor.taskpreview.AddInputDefinitionEvent;
import net.stogi.unicore.beyond.ui.client.taskeditor.taskpreview.AddInputGroupEvent;
import net.stogi.unicore.beyond.ui.client.taskeditor.taskpreview.AddOutputDefinitionEvent;
import net.stogi.unicore.beyond.ui.client.taskeditor.taskpreview.AddOutputGroupEvent;
import net.stogi.unicore.beyond.ui.shared.taskeditor.action.model.LoadInputTypesAction;
import net.stogi.unicore.beyond.ui.shared.taskeditor.action.model.LoadInputTypesResult;
import net.stogi.unicore.beyond.ui.shared.taskeditor.action.model.LoadOutputTypesAction;
import net.stogi.unicore.beyond.ui.shared.taskeditor.action.model.LoadOutputTypesResult;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

class IoToolboxPresenter extends AbstractPresenter {

	private IoToolboxView ioToolboxView;

	private List<InputType> inputTypes;

	private List<OutputType> outputTypes;

	public IoToolboxPresenter(IoToolboxView ioToolboxView, ActionManager actionManager, EventBus eventBus) {
		super(actionManager, eventBus);
		this.ioToolboxView = ioToolboxView;
		initBehavior();
		initHandlers();
		executeLoadInputTypes();
	}

	@Override
	protected void initBehavior() {
		// Behavior on adding new input group.
		ioToolboxView.setInputGroupBehavior(new Behavior() {

			@Override
			public void behave() {
				eventBus.fireEvent(new AddInputGroupEvent());
			}
		});
		// Behavior on adding new output group.
		ioToolboxView.setOutputGroupBehavior(new Behavior() {

			@Override
			public void behave() {
				eventBus.fireEvent(new AddOutputGroupEvent());
			}
		});
	}

	@Override
	protected void initHandlers() {}

	private void executeLoadInputTypes() {
		actionManager.execute(new LoadInputTypesAction(), new AsyncCallback<LoadInputTypesResult>() {

			@Override
			public void onFailure(Throwable caught) {
				// TODO: Add nice error handler.
				GWT.log("IoToolboxPresenter.executeLoadInputTypes.onFailure: error caught", caught);
			}

			@Override
			public void onSuccess(LoadInputTypesResult result) {
				GWT.log("IoToolboxPresenter.executeLoadInputTypes.onSuccess: result [ result.inputTypes.size = '"
						+ result.getInputTypes().size() + "']");

				inputTypes = result.getInputTypes();
				internalDisplayInputTypes(inputTypes);
			}
		});
		actionManager.execute(new LoadOutputTypesAction(), new AsyncCallback<LoadOutputTypesResult>() {

			@Override
			public void onFailure(Throwable caught) {
				// TODO: Add nice error handler.
				GWT.log("IoToolboxPresenter.executeLoadOutputTypes.onFailure: error caught", caught);
			}

			@Override
			public void onSuccess(LoadOutputTypesResult result) {
				GWT.log("IoToolboxPresenter.executeLoadOutputTypes.onSuccess: result [ result.outputTypes.size = '"
						+ result.getOutputTypes().size() + "']");

				outputTypes = result.getOutputTypes();
				internalDisplayOutputTypes(outputTypes);
			}
		});
	}

	private void internalDisplayInputTypes(List<InputType> inputTypes) {
		for (final InputType inputType : inputTypes) {
			ioToolboxView.addInputType(inputType.getName(), new Behavior() {

				@Override
				public void behave() {
					eventBus.fireEvent(new AddInputDefinitionEvent(inputType));
				}
			});
		}
	}
	
	private void internalDisplayOutputTypes(List<OutputType> outputTypes) {
		for (final OutputType outputType : outputTypes) {
			ioToolboxView.addOutputType(outputType.getName(), new Behavior() {

				@Override
				public void behave() {
					eventBus.fireEvent(new AddOutputDefinitionEvent(outputType));
				}
			});
		}
	}
}
